import { _decorator, Color, Component, math, Node, Size, sp, Sprite, SpriteFrame, Tween, tween, Vec2, Vec3 } from 'cc';
import { SpawnerCom, ISpawnerEventCall, SpawnEvent } from './SpawnerCom';
import { Unit, UnitEvent } from '../Unit';
import AssetsMgr from '../../Model/AssetsMgr';
import GameEventMgr, { GameEvent } from '../../Model/GameEventMgr';
import { Global, LootType, RelicType, UnitType } from '../../Util/Global';
import { EconomicCom } from './EconomicCom';
import { LevelUpCom } from './LevelUpCom';
const { ccclass, property } = _decorator;

/**工厂组件 */
@ccclass('FactoryCom')
export class FactoryCom extends Component implements ISpawnerEventCall {

    /**自身单位 */
    unit: Unit = null;

    public spawner: SpawnerCom = null;

    protected _unitChildren: Unit[] = [];

    @property
    public autoWorking: boolean = true;

    tweenAnim: Tween<Node> = null;

    iconNode: Node = null;
    levelCom: LevelUpCom = null;
    start() {
        this.unit = this.node.getComponent(Unit);

        this.spawner = this.getComponent(SpawnerCom);
        if (this.spawner == null) {
            this.spawner = this.addComponent(SpawnerCom);
        }
        this.spawner.Reset();

        // this.spawner.AddProduct(AssetsMgr.getUnitPrefab(UnitType.UnitAssault));
        // this.spawner.AddProduct(AssetsMgr.getUnitPrefab(UnitType.UnitMining));

        this.spawner.getSpawnChildren(this._unitChildren);
        this.spawner.onSpawnEventCallback('FactoryComHandle', this);
        // this.spawner.AddProductNum(UnitType.Assault, 1);

        this.levelCom = this.node.getComponent(LevelUpCom) || this.node.addComponent(LevelUpCom);
        this.levelCom.spawner = this.spawner;
        if (this.unit != Global.gameManager.playerUnit) {
            this.levelCom.level = Global.gameManager.playerData.difficulty;
        }

        AssetsMgr.getRes("texture/factory_icon/spriteFrame", SpriteFrame, (icon) => {
            if (!this.unit || !this.unit.node) {
                return;
            }
            this.iconNode = new Node();
            this.iconNode.parent = this.unit.node;
            this.iconNode.scale = new Vec3(0.8, 0.8, 1)
            let sprite = this.iconNode.addComponent(Sprite);
            sprite.spriteFrame = icon as SpriteFrame;
            sprite.color = Color.BLACK;

            this.tweenAnim = tween(this.iconNode).by(1, { angle: -360 }).repeatForever();
        })

        GameEventMgr.Register(this, GameEvent.EconomicComBroken, this.OnEconmicBroken.bind(this));
    }

    protected onDisable(): void {
        // this.spawner.ClearWorkShop();
        // this._unitChildren = [];
        this.unit = null;
        if (this.iconNode) {
            this.iconNode.destroy();
        }
        this.destroy();
    }

    private static _LootSpawnWeight = new Map<RelicType, number>([
        [RelicType.DysonTrackPlanA, 100],
        [RelicType.DysonTrackPlanB, 100],
        [RelicType.LightParticleStrike, 100],
    ]);

    /**随机权重计算出掉落物类型 */
    getRandomLootTypeByWeight(): RelicType {

        if (Math.random() > 0.3) {//3成概率掉落
            return null;
        }

        let totalWeight = 0;
        FactoryCom._LootSpawnWeight.forEach(v => {
            totalWeight += v;
        })
        let weight = Math.random() * totalWeight;
        let sum = 0;
        let target: RelicType = null;
        for (let kv of FactoryCom._LootSpawnWeight) {
            sum += kv[1];
            target = kv[0];
            if (sum > weight) {
                break;
            }
        }
        return target;
    }

    OnEconmicBroken(unit: Unit) {
        if ((unit && unit != this.unit) || !this.isValid) {//有肯能被子弹销毁同时又被撞毁了
            return;
        };

        this.unit.dispatch(UnitEvent.EconomicComBroken, this.unit);

        GameEventMgr.UnRegister(this, GameEvent.EconomicComBroken);
        this.unit.playerCtrl = false;

        //掉落资源
        let playerData = Global.gameManager.playerData;
        //掉落资源和科技
        Global.gameManager.mapCtrl.mapSpawner.
            SpawnUnitImmediatelyLoot(LootType.Technology, this.unit.unitWorldPos, 3, 50 * playerData.difficulty);
        Global.gameManager.mapCtrl.mapSpawner.
            SpawnUnitImmediatelyLoot(LootType.Mine, this.unit.unitWorldPos, 3, 100 * playerData.difficulty);

        let relic = this.getRandomLootTypeByWeight();
        if (relic) {
            Global.gameManager.mapCtrl.mapSpawner.SpawnUnitImmediatelyLoot(LootType.Relic, this.unit.unitWorldPos, 1, relic);
        }

        this.unit = null;
        this?.destroy();
        this.iconNode?.destroy();
        this.spawner.DestroyAllChildren('工厂组件销毁');
    }

    update(deltaTime: number) {
        if (Global.gameManager.pause) {
            return;
        }

        if (this.autoWorking) {//自动生产 AI
            let spawnMax = this.levelCom ? this.levelCom.level * 5 : 5;

            let global_spacecra_num = Global.gameManager.get_all_unit_count(UnitType.UnitSpacecra);
            if (global_spacecra_num > 200) {//单位爆了！！！暂停孵化！
                return;
            }

            if (this._unitChildren.length + this.spawner.spawningCount < spawnMax) {
                //找到经济模块
                let economic = this.getComponent(EconomicCom);
                //找到生产车间
                if (economic) {//如果有经济组件就消耗资源
                    let workshops = this.spawner.GetIdleWorkShops();
                    for (let i = 0; i < workshops.length; i++) {
                        let work = workshops[i];
                        let productPrefeb = work.prefeb;
                        let unit: Unit = productPrefeb.data.getComponent(Unit);

                        let producingCost = this.spawner.GetElectricConsume_afterCompletingProduction();
                        let cost = unit.spawn_cost;

                        if (unit.unitType == UnitType.UnitMining) {//人机资源飞船不消耗矿材
                            cost = 0;
                        }
                        //消耗资源
                        if (economic.HasRes(cost, producingCost)) {
                            economic.CostRes(unit.spawn_cost);
                            this.spawner.AddProductNum(work.productType, 1);
                        }
                    }
                }
                else {
                    this.spawner.StartIdleWorkShop();
                }
            }
        }
    }

    SpawnEventCallback(unit: Unit, event: SpawnEvent) {
        if (event == SpawnEvent.SPAWNING) {
            if (unit.isValid) {
                if (this.isValid) {
                    this.onChildSpwaned(unit);
                }
                else {
                    unit.DestroySelf();
                }
            }
        }
        else if (event == SpawnEvent.START) {
            this.tweenAnim && this.tweenAnim.start();//生产icon旋转动画
        }
        else if (event == SpawnEvent.END) {
            this.tweenAnim && this.tweenAnim.stop();
        }

        return true;
    }

    /**子单位孵化 */
    protected onChildSpwaned(child: Unit) {
        // child.setDestroyCallback(this.onChildDestroy.bind(this));
        child.on(this, UnitEvent.OnDestroy, this.onChildDestroy.bind(this));

        let economic = this.getComponent(EconomicCom);
        if (economic) {
            economic.AddPowerConsumer(child);
        }

        if (this.unit) {
            child.SetBodyColor(this.unit.GetBodyColor());
        }
    }

    /**子单位销毁 */
    protected onChildDestroy(child: Unit) {
        if (this && this.isValid) {

            let index = this._unitChildren.indexOf(child);
            if (index !== -1) {
                this._unitChildren.splice(index, 1);
            }

            let economic = this.getComponent(EconomicCom);
            if (economic) {
                economic.RemovePowerConsumer(child);
            }
        }
    }
}


